//
//  documents.m
//  iCodeMac
//
//  Created by Andrew Barry on 27/04/09.
//  Copyright 2009 Barry Computer Services. All rights reserved.
//

#import "documents.h"
#import "WrappedJsval.h"
#import "AppLoader.h"
#import "JavascriptProject.h"
#import "DebugConnection.h"

static jsvalue getRecentDocuments(jscontext *cx, jsframe *outer, jsvalue obj, jsvalue *args, int argc) {
	NSDocumentController *controller =
	[NSDocumentController sharedDocumentController];
	NSArray *documents = [controller recentDocumentURLs];
	int len = [documents count];
	
	jsvalue rv = jsnewarray(cx);
	jsaddstackroot(cx, rv);
	
	for (int idx = 0; idx < len; idx++) {
		NSURL *url = [documents objectAtIndex:idx];
		NSString *path = [url absoluteString];
		jspush(cx, rv, jsstrFromNSString(cx, path));
	}
	
	return rv;
}

static jsvalue openDocumentURL(jscontext *cx, jsframe *outer, jsvalue obj, jsvalue *args, int argc) {
	if (argc < 1)
		return JSVAL_VOID;
	NSString *urlStr = jsasstrRetain(cx, args[0]);
	NSURL *url = [NSURL URLWithString:urlStr];
	[urlStr release];
	[[NSDocumentController sharedDocumentController] openDocumentWithContentsOfURL:url display:YES error:nil];
	return JSVAL_VOID;
}

static jsvalue newProjectAction(jscontext *cx, jsframe *outer, jsvalue obj, jsvalue *args, int argc) {
	AppLoader *app = [NSApp delegate];
	[app newProject:nil];
	return JSVAL_VOID;
}

static jsvalue openProjectAction(jscontext *cx, jsframe *outer, jsvalue obj, jsvalue *args, int argc) {
	[[NSDocumentController sharedDocumentController] openDocument:nil];
	return JSVAL_VOID;
}

static jsvalue ideShowLine(jscontext *cx, jsframe *outer, jsvalue obj, jsvalue *args, int argc) {
	NSString *debugKey = [jsasstrRetain(cx, args[0]) autorelease];
	NSString *script = [jsasstrRetain(cx, args[1]) autorelease];
	int nLine = jsasint(cx, args[2]);

	JavascriptProject *proj = projectForDebugKey(debugKey);
	if (proj) {
		[proj displaySource:script atLine:nLine];
	}
	
	return JSVAL_VOID;
}

static jsvalue getProjectProperty(jscontext *cx, jsframe *outer, jsvalue obj, jsvalue *args, int argc) {
	NSString *projURL = [jsasstrRetain(cx, args[0]) autorelease];
	NSString *propName = [jsasstrRetain(cx, args[1]) autorelease];

	JavascriptProject *proj = [[NSDocumentController sharedDocumentController] documentForURL:[NSURL URLWithString:projURL]];
	if (!proj) {
		return JSVAL_VOID;
	}
	NSObject *v = [proj getProperty: propName];
	if ([v isKindOfClass:[NSString class]]) {
		return jsstrFromNSString(cx, (NSString *) v);
	} else if ([v isKindOfClass:[NSNumber class]]) {
		return jsnumi(cx, [(NSNumber *) v intValue]);
	}
	return JSVAL_VOID;
}

static jsvalue setProjectProperties(jscontext *cx, jsframe *outer, jsvalue me, jsvalue *args, int argc) {
	NSString *projURL = [jsasstrRetain(cx, args[0]) autorelease];
	jsvalue props = args[1];

	JavascriptProject *proj = [[NSDocumentController sharedDocumentController] documentForURL:[NSURL URLWithString:projURL]];
	if (!proj) {
		return JSVAL_VOID;
	}
	
	jsobject *obj = JSVAL_TO_OBJECT(props);
	NSMutableDictionary *projectProps = [NSMutableDictionary new];

	for (jsfield *fld = obj->fields; fld; fld = fld->next) {
		
		NSString *keyStr = jsasstrRetain(cx, fld->field);
		jsvalue keyVal = fld->val;
		if (JSVAL_IS_STRING(keyVal)) {
			NSString *strVal = [jsasstrRetain(cx, keyVal) autorelease];
			[projectProps setObject:strVal forKey:keyStr];
		} else if (JSVAL_IS_BOOLEAN(keyVal)) {
			[projectProps setObject:[NSNumber numberWithBool:JSVAL_TO_BOOLEAN(keyVal)] forKey:keyStr];
		} else if (JSVAL_IS_INT(keyVal)) {
			[projectProps setObject:[NSNumber numberWithInt:JSVAL_TO_INT(keyVal)] forKey:keyStr];
		} else if (JSVAL_IS_NUMBER(keyVal)) {
			double v = jsasnum(cx, keyVal);
			[projectProps setObject:[NSNumber numberWithDouble:v] forKey:keyStr];
		}
		[keyStr release];
	}
	
	[proj setProjectProperties: projectProps];
	return JSVAL_VOID;
}

void registerDocuments(jscontext *cx) {
	jsvalue System = cx->slots[13];
	
	jsset(cx, System, 0, "recentDocuments", bindFunction(cx, getRecentDocuments));
	jsset(cx, System, 0, "openDocumentURL", bindFunction(cx, openDocumentURL));
	jsset(cx, System, 0, "newProjectAction", bindFunction(cx, newProjectAction));
	jsset(cx, System, 0, "openProjectAction", bindFunction(cx, openProjectAction));
	jsset(cx, System, 0, "ideShowLine", bindFunction(cx, ideShowLine));
	jsset(cx, System, 0, "getProjectProperty", bindFunction(cx, getProjectProperty));
	jsset(cx, System, 0, "setProjectProperties", bindFunction(cx, setProjectProperties));
}
